/*
 * Copyright (C) 2012 JiangHongTiao
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package sk.lieskove.jianghongtiao.paris.core.classify.enums;

import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import weka.classifiers.Classifier;
import weka.classifiers.bayes.BayesNet;
import weka.classifiers.bayes.NaiveBayes;
import weka.classifiers.bayes.NaiveBayesUpdateable;
import weka.classifiers.functions.LibSVM;
import weka.classifiers.functions.Logistic;
import weka.classifiers.functions.MultilayerPerceptron;
import weka.classifiers.functions.SGD;
import weka.classifiers.functions.SMO;
import weka.classifiers.functions.SimpleLogistic;
import weka.classifiers.functions.VotedPerceptron;
import weka.classifiers.lazy.LWL;
import weka.classifiers.meta.AdaBoostM1;
import weka.classifiers.meta.AttributeSelectedClassifier;
import weka.classifiers.meta.Bagging;
import weka.classifiers.meta.CVParameterSelection;
import weka.classifiers.meta.ClassificationViaRegression;
import weka.classifiers.meta.CostSensitiveClassifier;
import weka.classifiers.meta.FilteredClassifier;
import weka.classifiers.meta.LogitBoost;
import weka.classifiers.meta.MultiClassClassifier;
import weka.classifiers.meta.MultiClassClassifierUpdateable;
import weka.classifiers.meta.RandomCommittee;
import weka.classifiers.meta.RandomSubSpace;
import weka.classifiers.rules.JRip;
import weka.classifiers.rules.OneR;
import weka.classifiers.rules.PART;
import weka.classifiers.trees.DecisionStump;
import weka.classifiers.trees.J48;
import weka.classifiers.trees.LMT;
import weka.classifiers.trees.REPTree;
import weka.classifiers.trees.RandomForest;
import weka.classifiers.trees.RandomTree;

/**
 *
 * @author xjuraj
 */
public enum SupportedClassifiers {
    
    //-----------TREES----------
    DecisionStump(new DecisionStump()),
    J48(new J48()),
    LMT(new LMT()),
    RandomForest(new RandomForest()),
    RandomTree(new RandomTree()),
    REPTree(new REPTree()),
    //------------RULES---------
    JRip(new JRip()),
    OneR(new OneR()),
    PART(new PART()),
    //-----------BAYES----------
    BayesNet(new BayesNet()),
    NaiveBayes(new NaiveBayes()),
    NaiveBayesUpdateable(new NaiveBayesUpdateable()),
    //---------FUNCTIONS--------
    LibSVM(new LibSVM()),
    Logistic(new Logistic()),
    MultilayerPerceptron(new MultilayerPerceptron()),
    SGD(new SGD()),
    SimpleLogistic(new SimpleLogistic()),
    SMO(new SMO()),
    VotedPerceptron(new VotedPerceptron()),
    //-----------LAZY-----------
    LWL(new LWL()),
    //-----------META-----------
    AdaBoostM1(new AdaBoostM1()),
    AttributeSelectedClassifier(new AttributeSelectedClassifier()),
    Bagging(new Bagging()),
    ClassificationViaRegression(new ClassificationViaRegression()),
    CostSensitiveClassifier(new CostSensitiveClassifier()),
    CVParameterSelection(new CVParameterSelection()),
    FilteredClassifier(new FilteredClassifier()),
    LogitBoost(new LogitBoost()),
    MultiClassClassifier(new MultiClassClassifier()),
    MultiClassClassifierUpdateable(new MultiClassClassifierUpdateable()),
    RandomCommittee(new RandomCommittee()),
    RandomSubSpace(new RandomSubSpace()),
    ;
    
    private final Classifier value;
    private static transient Logger log = Logger.getLogger("SupportedClassifiers");
    
    SupportedClassifiers(Classifier v) {
        value = v;
    }
    
    public Classifier value() {
        return value;
    }
    
    public SupportedClassifiers fromValue(Classifier v) {
        for (SupportedClassifiers c : SupportedClassifiers.values()) {
            if (c.value.equals(v)) {
                return c;
            }
        }
        throw new IllegalArgumentException("Value '" + v
                + "' is not correct value for type " + SupportedClassifiers.class.getName());
    }
    
    public boolean containsValue(Classifier v) {
        for (SupportedClassifiers c : SupportedClassifiers.values()) {
            if (c.value.equals(v)) {
                return true;
            }
        }
        return false;
    }
    
    public static Classifier byName(String name){
        name = name.toLowerCase();
        for (SupportedClassifiers c : SupportedClassifiers.values()) {
            if (c.name().toLowerCase().equals(name)) {
                try {
                    Class forName = Class.forName(c.value().getClass().getCanonicalName());
                    return (Classifier) forName.newInstance();
                } catch (InstantiationException ex) {
                    log.error("InstantiationException", ex);
                } catch (IllegalAccessException ex) {
                    log.error("IllegalAccessException", ex);
                } catch (ClassNotFoundException ex) {
                    log.error("Cannot create class for class: "+
                            c.value().getClass().getCanonicalName(), ex);
                }
            }
        }
        return null;
    }
    
    public static List<String> asNameList(){
        List<String> result = new ArrayList<String>();
        for (SupportedClassifiers c : SupportedClassifiers.values()) {
            result.add(c.name());
        }
        return result;
    }
}
